/*
 * MosaicMe - Digital Art Application
 * Author: Gonzalo Luzardo
 * Collaborators: Manuel Abellanas, Giacomo Bartoloni 
 * 
 * General Mosaic Information at: http://en.wikipedia.org/wiki/Mosaic
 */

import processing.core.*;
import JMyron.*;

public class MosaicMe extends PApplet {

	private static final long serialVersionUID = 1L;
	
	private JMyron m_movie; //Capture manager
	private PImage m_img_frame; //Current frame buffer
	private FaceDetectionManager m_face_detection_manager; //Face detection manager
	private DelaunayTriangulationCreator m_delaunay_creator; //Delaunay Triangulation creator
	private MosaicCreator m_mosaic_creator;
	private XMLConfLoader m_xml_conf_loader; //XML configuration loader
	
	private PImage m_logo; //Application logo
	private boolean m_make_animation;
	
	//Use only like initializer
	static {
		//Libraries used by JMyron
		System.loadLibrary("DSVL");
		System.loadLibrary("myron_ezcam");	
		//Libraries for openGL
		
    }
	
	//Constructor
	public MosaicMe(){
		System.out.println("Starting MosaicMe constructor...");
		m_xml_conf_loader = new XMLConfLoader("config.xml");
		System.out.println("Try to read XML file...");
		try{
			m_xml_conf_loader.parseXML();
		}
		catch(XMLConfLoaderException e){
			System.err.println(e.getMessage());
			System.out.println("Setting default parameters ...");
			m_xml_conf_loader.setDefaultParameters();
		}
		System.out.println("XML file readed...");
		
		//Load logo
		m_logo = loadImage("logo_mosaic_me.jpg");
	}
		
	//Setup processing environment and initialization
	public void setup() {
		System.out.println("\nStarting VitralMe setup...");
		
		//Setting color mode
		colorMode(RGB,255,255,255,10);
		
		//Size of output windows
		size(m_xml_conf_loader.getMosaicWidth(), m_xml_conf_loader.getMosaicHeight());
		m_movie = new JMyron();
		System.out.println("Loading capture...");
		
		//Star with size of window
		m_movie.start(m_xml_conf_loader.getVideoWidth(),m_xml_conf_loader.getVideoHeight());
		m_movie.findGlobs(0);
		m_face_detection_manager = new FaceDetectionManager(this,
															m_xml_conf_loader.getVideoWidth(),
															m_xml_conf_loader.getVideoHeight(),
															m_xml_conf_loader.getClassifierFile(), 
															m_xml_conf_loader.getFaceWatchMinTime());
		
		//Delaunay creator
		m_delaunay_creator = new DelaunayTriangulationCreator(this,
											 				  m_xml_conf_loader.getMosaicWidth(),
											 				  m_xml_conf_loader.getMosaicHeight(),
											 				  m_xml_conf_loader.getMosaicEdgePixels(),
											 				  m_xml_conf_loader.getMosaicRandomPixels());
		
		//Mosaic Creator
		m_mosaic_creator = new MosaicCreator(this,true,false,false);
		
	
		//Logo
		m_logo = loadImage("logo_mosaic_me.jpg");
	
		//Image frames
		m_img_frame = createImage(m_xml_conf_loader.getVideoWidth(),
							      m_xml_conf_loader.getVideoHeight(),
							      RGB);
		
		m_make_animation = true;
		
		frameRate(24);
		rectMode(CORNER);
		smooth();
		System.out.println("Capture loaded...");
		System.out.println("Finalize VitralMe setup...");
	}
	
	
	// Draw function 
    public void draw() {  	   	 
    	if(m_make_animation){
    		background(255);
        	image(m_logo,(int)((width-m_logo.width)*0.5),(int)((height-m_logo.height)*0.5));
        	m_make_animation = false;
    	}
    	else{
    		//Get image from camera
        	m_movie.update();
        	//Copy to m_img_frame
        	m_movie.cameraImageCopy(m_img_frame.pixels);
        	
        	//Try to process mosaic
        	m_face_detection_manager.processImage(m_img_frame);
        	if(m_face_detection_manager.getWatchCounter() > m_xml_conf_loader.getFaceWatchMinTime()){
        		//Reset counter
        		m_face_detection_manager.resetWatchCounter();
        		System.out.println("Getting mosaic from face(s) detected...");
        		
        		//Get mosaic
        		int [][] res = m_face_detection_manager.getAreaFaceDetected(); //Get detected face area
        		m_delaunay_creator.process(m_img_frame, 
        						 res[0][0], 
        						 res[0][1], 
        						 res[1][0], 
        						 res[1][1]);
        		m_mosaic_creator.createMosaic(m_delaunay_creator);
        	}
        	loadPixels();
        	updatePixels();
    	}
    }
    
    //Draw area faces
    @SuppressWarnings("unused")
	private void drawAreaFaces(){
    	noFill();
		stroke(255,0,0);
		int [][] res = m_face_detection_manager.getAreaFaceDetected();
		if (res != null) 
    	   rect(res[0][0],res[0][1],res[1][0]-res[0][0],res[1][1]-res[0][1]);
    	
    }
    
    
    //Draw rectangle over each face detection
    @SuppressWarnings("unused")
	private void drawFaces() {
    	noFill();
		stroke(255,0,0);
    	int [][] res = m_face_detection_manager.getFacesDetected();
    	  if (res.length>0) {
    	    for (int i=0;i<res.length;i++) {
    	      int x = res[i][0];
    	      int y = res[i][1];
    	      int w = res[i][2];
    	      int h = res[i][3];
    	      rect(x,y,w,h);
    	    }
    	  }
    	}
    
    public void stop() {
    	m_movie.stop();
    	super.stop();
    }
    
    static public void main(String args[]) {
    	System.loadLibrary("DSVL");
		System.loadLibrary("myron_ezcam");	
		PApplet.main(new String[] { "--present","MosaicMe"});
	}

}



